﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;

namespace Shared
{
    internal static class DatabaseInfo
    {
        private readonly static LinkedList<PKS> _dbPrimaryKeys = new LinkedList<PKS>();
        private struct PKS
        {
            public string CS;
            public Dictionary<string, string> PKLookup;
        }
        internal static string GetPrimaryKeyName(SqlCeConnection cnn, string tableName)
        {
            string cs = cnn.ConnectionString;

            var node = _dbPrimaryKeys.First;
            while (node != null && !node.Value.CS.Equals(cs)) node = node.Next;

            if (node == null)
            {
                //TODO check for threading issues
                _dbPrimaryKeys.AddLast(node = new LinkedListNode<PKS>(new PKS() { CS = cnn.ConnectionString, PKLookup = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) }));

                foreach (var ix in GetData(cnn)) if (ix.PrimaryKey) node.Value.PKLookup[ix.TableName] = ix.IndexName;
            }

            string pkName;
            if (node.Value.PKLookup.TryGetValue(tableName, out pkName)) return pkName;

            throw new Exception("Could not find PrimaryKey for table '" + tableName + "'.");
        }

        internal static string[] GetPrimaryKeyColumnNames(SqlCeConnection cnn, string tableName)
        {
            return GetData(cnn)
                    .Where(ix => ix.PrimaryKey && ix.TableName.Equals(tableName, StringComparison.OrdinalIgnoreCase))
                    .OrderBy(ix => ix.Ordinal)
                    .Select(ix => ix.ColumnName)
                    .ToArray();
        }



        internal struct IndexColumn
        {
            public string TableName { get; set; }
            public string ColumnName { get; set; }
            public bool PrimaryKey { get; set; }
            public string IndexName { get; set; }
            //public bool Unique { get; set; }
            public short Ordinal { get; set; }
        }

        //TODO fix for different databases.
        private static IndexColumn[] _indexColumns;
        internal static IndexColumn[] GetData(SqlCeConnection cnn)
        {

            if (_indexColumns == null)
            {
                List<IndexColumn> ls = new List<IndexColumn>();
                using (SqlCeCommand cmd = new SqlCeCommand("SELECT * FROM INFORMATION_SCHEMA.INDEXES", cnn))
                using (var dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        ls.Add(new IndexColumn()
                        {
                            TableName = (string)dr["TABLE_NAME"],
                            ColumnName = (string)dr["COLUMN_NAME"],
                            PrimaryKey = true.Equals(dr["PRIMARY_KEY"]),
                            //Unique = true.Equals(dr["UNIQUE"]),
                            IndexName = (string)dr["INDEX_NAME"],
                            Ordinal = (short)(int)dr["ORDINAL_POSITION"]
                        });
                    }
                }
                _indexColumns = ls.ToArray();
            }
            return _indexColumns;
        }
    }
}